#include "lcd_init.h"
#include "stdio.h"
#include <string.h>

typedef void (*FunType)(void);

extern SPI_HandleTypeDef hspi1;

uint16_t eline[240] = {0};
uint16_t oline[240] = {0};
uint16_t line55[240] = {0};
uint16_t lineaa[240] = {0};

static inline void LCD_CSHigh(void)
{
	HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);
}
static inline void LCD_CSLow(void)
{
	HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_RESET);
}
static inline void LCD_DCXHigh(void)
{
	HAL_GPIO_WritePin(DC_GPIO_Port, DC_Pin, GPIO_PIN_SET);
}
static inline void LCD_DCXLow(void)
{
	HAL_GPIO_WritePin(DC_GPIO_Port, DC_Pin, GPIO_PIN_RESET);
}

void wr_cmd_4spi_8bcs(uint8_t par)
{
	LCD_DCXLow();
	LCD_CSLow();

	HAL_SPI_Transmit(&hspi1, &par, 1, 0xFFF);

	LCD_CSHigh();
	LCD_DCXHigh();
}
void wr_dat_4spi_8bcs(uint8_t par)
{
	LCD_CSLow();

	HAL_SPI_Transmit(&hspi1, &par, 1, 0xFFF);

	LCD_CSHigh();
}
#if 0
void wr_cmd_parall1_8(uint16_t par)
{
    LCD_DCXLow();
    LCD_CSLow();
    LCD_WRLow();
    GPIOB->ODR = par;

    LCD_WRHigh();
}
void wr_dat_parall1_8(uint16_t par)
{
    LCD_DCXHigh();
    LCD_WRLow();
    GPIOB->ODR = par;

    LCD_WRHigh();
}
void wr_cmd_parall2_8(uint16_t par)
{
    LCD_DCXLow();
    LCD_CSLow();
    LCD_WRLow();
    GPIOB->ODR = par << 1;

    LCD_WRHigh();
}
void wr_dat_parall2_8(uint16_t par)
{
    LCD_DCXHigh();
    LCD_WRLow();
    GPIOB->ODR = par << 1;

    LCD_WRHigh();
}
void wr_cmd_parall1_16(uint16_t par)
{
    LCD_DCXLow();
    LCD_CSLow();
    LCD_WRLow();
    GPIOB->ODR = par;

    LCD_WRHigh();
}
void wr_dat_parall1_16(uint16_t par)
{
    LCD_DCXHigh();
    LCD_WRLow();
    GPIOB->ODR = par;

    LCD_WRHigh();
}
void wr_displ_parall1_18(uint16_t color1, uint16_t color2)
{
    LCD_DCXHigh();
    LCD_WRLow();
    if (color1 & 0x02)
        HAL_GPIO_WritePin(DB17_GPIO_Port, DB17_Pin, GPIO_PIN_SET);
    else
        HAL_GPIO_WritePin(DB17_GPIO_Port, DB17_Pin, GPIO_PIN_RESET);
    if (color1 & 0x01)
        HAL_GPIO_WritePin(DB16_GPIO_Port, DB16_Pin, GPIO_PIN_SET);
    else
        HAL_GPIO_WritePin(DB16_GPIO_Port, DB16_Pin, GPIO_PIN_RESET);
    GPIOB->ODR = color2;
    LCD_WRHigh();
}
#endif
void HW_Reset(void)
{
	// LCD_RSTHigh();
	HAL_GPIO_WritePin(RST_GPIO_Port, RST_Pin, GPIO_PIN_SET);
	HAL_Delay(120);
	// LCD_RSTLow();
	HAL_GPIO_WritePin(RST_GPIO_Port, RST_Pin, GPIO_PIN_RESET);
	HAL_Delay(120);
	// LCD_RSTHigh();
	HAL_GPIO_WritePin(RST_GPIO_Port, RST_Pin, GPIO_PIN_SET);
	HAL_Delay(200);

	for (int i = 0; i < 240; i += 2) {
		eline[i] = 0xffff;
		eline[i + 1] = 0x0000;
	}
	for (int i = 0; i < 240; i += 2) {
		oline[i] = 0x0000;
		oline[i + 1] = 0xffff;
	}

	for (int i = 0; i < 240; i++) {
		line55[i] = 0x5555;
		lineaa[i] = 0xaaaa;
	}
}

void Delay(uint32_t ms)
{
	HAL_Delay(ms);
}

void Write(uint8_t type, uint16_t dat)
{
	if (type == 0) {
		wr_cmd_4spi_8bcs(dat);
	} else {
		wr_dat_4spi_8bcs(dat);
	}
}

void CTRL_IO(GPIO_TypeDef *port, uint16_t pin, uint16_t state)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};

	GPIO_InitStruct.Pin = pin;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	HAL_GPIO_Init(port, &GPIO_InitStruct);

	// LCD_RSTHigh();
	HAL_GPIO_WritePin(port, pin, state);
}

void YTC272210LAA_246_100N(void)
{

	/****************并口0-7bit*****************/
	HAL_GPIO_WritePin(IM0_GPIO_Port, IM0_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(IM1_GPIO_Port, IM1_Pin, GPIO_PIN_SET);
	HAL_GPIO_WritePin(IM2_GPIO_Port, IM2_Pin, GPIO_PIN_SET);
	// CTRL_IO(GPIOC,GPIO_PIN_13,0);
	// CTRL_IO(GPIOC,GPIO_PIN_14,1);
	// CTRL_IO(GPIOC,GPIO_PIN_15,1);
	HW_Reset();

	Delay(120); // ms

	Write(Command, 0x11);

	Delay(120); // ms

	Write(Command, 0x36);
	Write(Parameter, 0x00);

	Write(Command, 0x3A);
	Write(Parameter, 0x05);

	Write(Command, 0xB2);
	Write(Parameter, 0x0C);
	Write(Parameter, 0x0C);
	Write(Parameter, 0x00);
	Write(Parameter, 0x33);
	Write(Parameter, 0x33);

	Write(Command, 0xB7);
	Write(Parameter, 0x46); // VGH=13.65V,VGL=-11.38V

	Write(Command, 0xBB);
	Write(Parameter, 0x1B);

	Write(Command, 0xC0);
	Write(Parameter, 0x2C);

	Write(Command, 0xC2);
	Write(Parameter, 0x01);

	Write(Command, 0xC3);
	Write(Parameter, 0x0F);

	Write(Command, 0xC4);
	Write(Parameter, 0x20);

	Write(Command, 0xC6);
	Write(Parameter, 0x0F);

	Write(Command, 0xD0);
	Write(Parameter, 0xA4);
	Write(Parameter, 0xA1);

	Write(Command, 0xD6);
	Write(Parameter, 0xA1);

	Write(Command, 0xE0);
	Write(Parameter, 0xF0);
	Write(Parameter, 0x00);
	Write(Parameter, 0x06);
	Write(Parameter, 0x04);
	Write(Parameter, 0x05);
	Write(Parameter, 0x05);
	Write(Parameter, 0x31);
	Write(Parameter, 0x44);
	Write(Parameter, 0x48);
	Write(Parameter, 0x36);
	Write(Parameter, 0x12);
	Write(Parameter, 0x12);
	Write(Parameter, 0x2B);
	Write(Parameter, 0x34);

	Write(Command, 0xE1);
	Write(Parameter, 0xF0);
	Write(Parameter, 0x0B);
	Write(Parameter, 0x0F);
	Write(Parameter, 0x0F);
	Write(Parameter, 0x0D);
	Write(Parameter, 0x26);
	Write(Parameter, 0x31);
	Write(Parameter, 0x43);
	Write(Parameter, 0x47);
	Write(Parameter, 0x38);
	Write(Parameter, 0x14);
	Write(Parameter, 0x14);
	Write(Parameter, 0x2C);
	Write(Parameter, 0x32);

	// Write(Command, 0xB0);
	// Write(Parameter, 0x10); // RGB interface
	// Write(Parameter, 0xF0); // 18BIT

	Write(Command, 0x21);

	Write(Command, 0x29);

	Write(Command, 0x2C);
}
// void Filllcd_Area(uint16_t _usX, uint16_t _usY, uint16_t _usWidth , uint16_t _usHeight, uint16_t color)

void Filllcd_Area(uint16_t color)
{
	uint32_t x = 0;
	uint32_t y = 0;

	wr_cmd_4spi_8bcs(0x2c);

	for (y = 0; y < LCD_Height; y++) {
		for (x = 0; x < LCD_Width; x++) {
			wr_dat_4spi_8bcs(color >> 8);
			wr_dat_4spi_8bcs(color);
		}
	}
}

void fill55(void)
{
	uint32_t x = 0;
	uint32_t y = 0;

	wr_cmd_4spi_8bcs(0x2c);

	for (y = 0; y < LCD_Height; y++) {
		LCD_CSLow();
		HAL_SPI_Transmit(&hspi1, (uint8_t *)&line55, 480, 0xFFF);
		LCD_CSHigh();
	}
}

void fillaa(void)
{
	uint32_t x = 0;
	uint32_t y = 0;

	wr_cmd_4spi_8bcs(0x2c);

	for (y = 0; y < LCD_Height; y++) {
		LCD_CSLow();
		HAL_SPI_Transmit(&hspi1, (uint8_t *)&lineaa, 480, 0xFFF);
		LCD_CSHigh();
	}
}

void chessa(void)
{
	uint32_t x = 0;
	uint32_t y = 0;

	wr_cmd_4spi_8bcs(0x2c);

	for (y = 0; y < LCD_Height / 2; y++) {
		for (x = 0; x < LCD_Width; x++) {
			wr_dat_4spi_8bcs(eline[x] >> 8);
			wr_dat_4spi_8bcs(eline[x]);
		}

		for (x = 0; x < LCD_Width; x++) {
			wr_dat_4spi_8bcs(oline[x] >> 8);
			wr_dat_4spi_8bcs(oline[x]);
		}
	}
}
void chessb(void)
{
	uint32_t x = 0;
	uint32_t y = 0;

	wr_cmd_4spi_8bcs(0x2c);

	for (y = 0; y < LCD_Height / 2; y++) {
		for (x = 0; x < LCD_Width; x++) {
			wr_dat_4spi_8bcs(oline[x] >> 8);
			wr_dat_4spi_8bcs(oline[x]);
		}

		for (x = 0; x < LCD_Width; x++) {
			wr_dat_4spi_8bcs(eline[x] >> 8);
			wr_dat_4spi_8bcs(eline[x]);
		}
	}
}

void disp_fullcolor(uint16_t color1, uint16_t color2)
{
    uint8_t fullcolor[480] = {0};
    // uint16_t real_color = (color1 << 8) & color2;
    printf("color is %02x %02x\n\r", color1, color2);
    wr_cmd_4spi_8bcs(0x2c);
    for (int i = 0; i < 480; i += 2)
    {
        fullcolor[i] = color1;
        fullcolor[i + 1] = color2;
    }
    for (int i = 0; i < LCD_Height; i++)
    {
        LCD_CSLow();
        HAL_SPI_Transmit(&hspi1, fullcolor, 480, 0xFFF);
    }
}

void lcd_frame(void)
{
    uint8_t fullcolor[480] = {0};
    wr_cmd_4spi_8bcs(0x2c);
    LCD_CSLow();
    for (int i = 0; i < 320; i++)
    {
        if ((i == 0) || (i == 319))
        {
            for (int j = 0; j < 480; j++)
            {
                fullcolor[j] = 0xFF;
            }
            HAL_SPI_Transmit(&hspi1, fullcolor, 480, 0xFFF);
        }
        else
        {
            for (int j = 0; j < 480; j += 2)
            {
                if ((j == 0) || (j == 478))
                {
                    fullcolor[j] = 0xFF;
                    fullcolor[j + 1] = 0xFF;
                }
                else
                {
                    fullcolor[j] = 0x00;
                    fullcolor[j + 1] = 0x00;
                }
            }
            HAL_SPI_Transmit(&hspi1, fullcolor, 480, 0xFFF);
        }
        // HAL_Delay(1000);
    }
}
extern const uint8_t gImage_image1[];

void disp_pic1(void)
{
    wr_cmd_4spi_8bcs(0x2c);
    LCD_CSLow();
    uint8_t image_arr[480] = {0};
    for (int j = 0; j < 320; j++)
    {
        for (int i = 0; i < 480; i++)
        {
            int k = j*480 + i;
            //printf("%02x\n\r",k);
            image_arr[i] = gImage_image1[k];
        }
        HAL_SPI_Transmit(&hspi1, image_arr, 480, 0xFFF);
    }
}

extern const uint8_t gImage_image2[];

void disp_pic2(void)
{
    wr_cmd_4spi_8bcs(0x2c);
    LCD_CSLow();
    uint8_t image_arr[480] = {0};
    for (int j = 0; j < 320; j++)
    {
        for (int i = 0; i < 480; i++)
        {
            int k = j*480 + i;
            //printf("%02x\n\r",k);
            image_arr[i] = gImage_image2[k];
        }
        HAL_SPI_Transmit(&hspi1, image_arr, 480, 0xFFF);
    }
}

extern const uint8_t gImage_image3[];

void disp_pic3(void)
{
    wr_cmd_4spi_8bcs(0x2c);
    LCD_CSLow();
    uint8_t image_arr[480] = {0};
    for (int j = 0; j < 320; j++)
    {
        for (int i = 0; i < 480; i++)
        {
            int k = j*480 + i;
            //printf("%02x\n\r",k);
            image_arr[i] = gImage_image3[k];
        }
        HAL_SPI_Transmit(&hspi1, image_arr, 480, 0xFFF);
    }
}